The Where clause contains the criteria limiting the notifications that the OPC UA server sends - and the OPC UA client receives. The Where clause in OPC UA is similar to the WHERE clause in SQL queries, with the difference that ity operates on events and not on table rows: It is a filter that allows you to choose the events of interest, out of all events provided by the chosen notifier node in the OPC UA server. The OPC UA server itself controls which events are generated by the notifier (for particular types of events, this may be prescribed by OPC UA specifications or other standards). For example, the event might be triggered by a process value exceeding specific limit. In OPC UA, there is no generic way to influence which events get internally generated in the OPC UA server; but the Where clause allows you to pick the events that are of interest to your application.
Obviously, you can also do event filtering on the client side (in your application), and throw away the events that you do not need. But this aproach requires all these events be transferred from the server to the client, which represents a load on all parts involved (server, network, client). Not all filtering criteria can be specified using the Where clause, but whenever you can, you should use it, because the filtering then occurs in the OPC UA server and close to the source, which greatly reduces the load on other parts of the system.
The Where clause of the event filter is represented using the UAContentFilterElement object. This objects contains the filter operand to be evaluated (the FilterOperator property, which is a UAFilterOperator enumeration), and the operands used by the selected operator (the FilterOperands property, which is a UAFilterOperandCollection). The UAFilterOperator enumeration contains all operators supported by OPC UA (Equals, IsNull, GreaterThan, LessThan, GreaterThanOrEqual, LessThanOrEqual, Like, Not, Between, InList, And, Or, Cast, InView, OfType, RelatedTo, BitwiseAnd, BitwiseOr). The UAFilterOperandCollection is a collection of content filter operands (UAFilterOperand).
The UAFilterOperand is a base class for four different types of filter operands: UAAttributeOperand (an operand consisting of an attribute of a node in a type, with optional relative path and alias), UAContentFilterElement (essentially, an operator with operands), UALiteralOperand (an operand consisting of a literal value), or UASimpleAttributeOperand (an operand consisting of an attribute of a node in a type, with optional simple relative path, and no alias).
In order to make the creation of Where clauses appear shorter in the code, a UAContentFilterElementBuilder class is provided. Instances of this builder can be implicitly converted to the content filter element itself (hence you can create just the UAContentFilterElementBuilder objects, and use them at all places where the UAContentFilterElement object is expected). The builder contains an operator and is a collection of operands; you can use the C# collection initializer to specify the operands.
For further simplification of the coding, the UAFilterElements static class provides an easy way to construct basic filter elements (literal, attribute, or a simple attribute), and elements with various operators. Using the UAFilterElements class is for most cases the recommended way to create the Where clause of the event filter. For example, UAFilterElements.GreaterThanOrEqual creates a Where clause with the ‘>=’ operator. There are methods for each of the OPC UA operators, with various overloads. The UAFilterElements.Attribute, UAFilterElements.Literal and UAFilterElements.SimpleAttribute methods can be used to create other types of filter elements. Moreover, useful overloads exist that assure that you can actually use .NET objects directly as values of operands, and they will be interpreted as literal elements. With use of all these code simplifying features, you can write, for example, the following Where clause:
UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500).
// This example shows how to specify criteria for event notifications. using System; using OpcLabs.EasyOpc.UA; using OpcLabs.EasyOpc.UA.AddressSpace; using OpcLabs.EasyOpc.UA.AddressSpace.Standard; using OpcLabs.EasyOpc.UA.AlarmsAndConditions; using OpcLabs.EasyOpc.UA.Filtering; using OpcLabs.EasyOpc.UA.OperationModel; namespace UADocExamples.AlarmsAndConditions { class WhereClause { public static void Main1() { UAEndpointDescriptor endpointDescriptor = "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer"; // Instantiate the client object and hook events. var client = new EasyUAClient(); client.EventNotification += client_EventNotification; Console.WriteLine("Subscribing..."); client.SubscribeEvent( endpointDescriptor, UAObjectIds.Server, 1000, new UAEventFilterBuilder( // Either the severity is >= 500, or the event comes from a specified source node UAFilterElements.Or( UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500), UAFilterElements.Equals( UABaseEventObject.Operands.SourceNode, new UANodeId("nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor"))), UABaseEventObject.AllFields)); Console.WriteLine("Processing event notifications for 30 seconds..."); System.Threading.Thread.Sleep(30 * 1000); Console.WriteLine("Unsubscribing..."); client.UnsubscribeAllMonitoredItems(); Console.WriteLine("Waiting for 5 seconds..."); System.Threading.Thread.Sleep(5 * 1000); Console.WriteLine("Finished."); } static void client_EventNotification(object sender, EasyUAEventNotificationEventArgs e) { // Display the event. Console.WriteLine(e); } // Example output: // //Subscribing... //13000008 //Processing event notifications for 30 seconds... //[] Success //[] Success; Refresh; RefreshInitiated //[] Success; Refresh; [SouthMotor] 100! {DialogConditionType} "The dialog was activated" @9/9/2021 2:22:18 PM (10 fields) //[] Success; Refresh; [SouthMotor] 700! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:17:59 AM (10 fields) //[] Success; Refresh; [SouthMotor] 900! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:17:57 AM (10 fields) //[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm is active." @9/22/2021 7:17:59 AM (10 fields) //[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:39:51 PM (10 fields) //[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:38:57 PM (10 fields) //[] Success; Refresh; RefreshComplete //[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:05 AM (10 fields) //[] Success; [SouthMotor] 300! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:08 AM (10 fields) //[] Success; [SouthMotor] 900! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:18:10 AM (10 fields) //[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm is active." @9/22/2021 7:18:13 AM (10 fields) //[] Success; [SouthMotor] 500! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:17 AM (10 fields) //[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:21 AM (10 fields) //[] Success; [SouthMotor] 300! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:21 AM (10 fields) //[] Success; [SouthMotor] 700! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:26 AM (10 fields) //[] Success; [SouthMotor] 500! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:29 AM (10 fields) //[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm is active." @9/22/2021 7:18:32 AM (10 fields) //Unsubscribing... //Waiting for 5 seconds... //Finished. } }
# This example shows how to specify criteria for event notifications. #requires -Version 5.1 using namespace OpcLabs.EasyOpc.UA using namespace OpcLabs.EasyOpc.UA.AddressSpace using namespace OpcLabs.EasyOpc.UA.AddressSpace.Standard # The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows . Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUA.dll" Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUAComponents.dll" # Define which server we will work with. [UAEndpointDescriptor]$endpointDescriptor = "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer" # Instantiate the client object. $client = New-Object EasyUAClient # Event notification handler Register-ObjectEvent -InputObject $client -EventName EventNotification -Action { # Display the event. Write-Host $EventArgs } Write-Host "Subscribing..." [IEasyUAClientExtension]::SubscribeEvent($client, $endpointDescriptor, [UAObjectIds]::Server, 1000, [UAEventFilter](New-Object UAEventFilterBuilder( [UAFilterElements]::Equals( [UABaseEventObject+Operands]::SourceNode, (New-Object UANodeId("nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor"))), [UABaseEventObject]::AllFields)) ) Write-Host "Processing event notifications for 30 seconds..." $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() while ($stopwatch.Elapsed.TotalSeconds -lt 30) { Start-Sleep -Seconds 1 } Write-Host "Unsubscribing..." $client.UnsubscribeAllMonitoredItems() Write-Host "Waiting for 5 seconds..." Start-Sleep -Seconds 5 Write-Host "Finished." # Example output: # #Subscribing... #13000008 #Processing event notifications for 30 seconds... #[] Success #[] Success; Refresh; RefreshInitiated #[] Success; Refresh; [SouthMotor] 100! {DialogConditionType} "The dialog was activated" @9/9/2021 2:22:18 PM (10 fields) #[] Success; Refresh; [SouthMotor] 700! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:17:59 AM (10 fields) #[] Success; Refresh; [SouthMotor] 900! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:17:57 AM (10 fields) #[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm is active." @9/22/2021 7:17:59 AM (10 fields) #[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:39:51 PM (10 fields) #[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:38:57 PM (10 fields) #[] Success; Refresh; RefreshComplete #[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:05 AM (10 fields) #[] Success; [SouthMotor] 300! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:08 AM (10 fields) #[] Success; [SouthMotor] 900! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:18:10 AM (10 fields) #[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm is active." @9/22/2021 7:18:13 AM (10 fields) #[] Success; [SouthMotor] 500! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:17 AM (10 fields) #[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:21 AM (10 fields) #[] Success; [SouthMotor] 300! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:21 AM (10 fields) #[] Success; [SouthMotor] 700! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:26 AM (10 fields) #[] Success; [SouthMotor] 500! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:29 AM (10 fields) #[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm is active." @9/22/2021 7:18:32 AM (10 fields) #Unsubscribing... #Waiting for 5 seconds... #Finished.
# This example shows how to specify criteria for event notifications. # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc import time # Import .NET namespaces. from OpcLabs.EasyOpc.UA import * from OpcLabs.EasyOpc.UA.AddressSpace import * from OpcLabs.EasyOpc.UA.AddressSpace.Standard import * from OpcLabs.EasyOpc.UA.AlarmsAndConditions import * from OpcLabs.EasyOpc.UA.Filtering import * from OpcLabs.EasyOpc.UA.OperationModel import * def eventNotification(sender, eventArgs): # Display the event. print(eventArgs) # Define which server we will work with. endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer') # Instantiate the client object and hook events. client = EasyUAClient() client.EventNotification += eventNotification print('Subscribing...') eventFilterBuilder = UAEventFilterBuilder( # Either the severity is >= 500, or the event comes from a specified source node. UAFilterElements.Or( UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500), UAFilterElements.Equals( UABaseEventObject.Operands.SourceNode, UANodeId('nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor'))), UABaseEventObject.AllFields) IEasyUAClientExtension.SubscribeEvent( client, endpointDescriptor, UANodeDescriptor(UAObjectIds.Server), 1000, UAEventFilterBuilder.ToUAEventFilter(eventFilterBuilder)) print('Processing event notifications for 30 seconds...') time.sleep(30) print('Unsubscribing...') client.UnsubscribeAllMonitoredItems() print('Waiting for 5 seconds...') time.sleep(5) print('Finished.')
' This example shows how to specify criteria for event notifications. Imports OpcLabs.EasyOpc.UA Imports OpcLabs.EasyOpc.UA.AddressSpace Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard Imports OpcLabs.EasyOpc.UA.AlarmsAndConditions Imports OpcLabs.EasyOpc.UA.Filtering Imports OpcLabs.EasyOpc.UA.OperationModel Namespace AlarmsAndConditions Friend Class WhereClause Public Shared Sub Main1() ' Instantiate the client object and hook events Dim client = New EasyUAClient() AddHandler client.EventNotification, AddressOf client_EventNotification Console.WriteLine("Subscribing...") ' Either the severity is >= 500, or the event comes from a specified source node client.SubscribeEvent( _ "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer", _ UAObjectIds.Server, _ 1000, _ New UAEventFilterBuilder( _ UAFilterElements.Or( _ UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500), UAFilterElements.Equals( _ UABaseEventObject.Operands.SourceNode, New UANodeId("nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor"))), UABaseEventObject.AllFields)) Console.WriteLine("Processing event notifications for 30 seconds...") Threading.Thread.Sleep(30 * 1000) Console.WriteLine("Unsubscribing...") client.UnsubscribeAllMonitoredItems() Console.WriteLine("Waiting for 5 seconds...") Threading.Thread.Sleep(5 * 1000) End Sub Private Shared Sub client_EventNotification(ByVal sender As Object, ByVal e As EasyUAEventNotificationEventArgs) ' Display the event Console.WriteLine(e) End Sub End Class End Namespace
// This example shows how to specify criteria for event notifications. type THelperMethods10 = class class function ObjectTypeIds_BaseEventType: _UANodeId; static; class function UABaseEventObject_Operands_EventId: _UASimpleAttributeOperand; static; class function UABaseEventObject_Operands_EventType: _UASimpleAttributeOperand; static; class function UABaseEventObject_Operands_NodeId: _UASimpleAttributeOperand; static; class function UAFilterElements_SimpleAttribute(TypeId: _UANodeId; simpleRelativeBrowsePathString: string): _UASimpleAttributeOperand; static; class function UABaseEventObject_Operands_SourceName: _UASimpleAttributeOperand; static; class function UABaseEventObject_Operands_Time: _UASimpleAttributeOperand; static; class function UABaseEventObject_Operands_ReceiveTime: _UASimpleAttributeOperand; static; class function UABaseEventObject_Operands_LocalTime: _UASimpleAttributeOperand; class function UABaseEventObject_Operands_SourceNode: _UASimpleAttributeOperand; static; class function UABaseEventObject_Operands_Message: _UASimpleAttributeOperand; static; class function UABaseEventObject_Operands_Severity: _UASimpleAttributeOperand; static; class function UABaseEventObject_AllFields: _UAAttributeFieldCollection; static; end; type TClientEventHandlers10 = class procedure Client_EventNotification( ASender: TObject; sender: OleVariant; const eventArgs: _EasyUAEventNotificationEventArgs); end; procedure TClientEventHandlers10.Client_EventNotification( ASender: TObject; sender: OleVariant; const eventArgs: _EasyUAEventNotificationEventArgs); begin // Display the event WriteLn(eventArgs.ToString); end; class procedure WhereClause.Main; const UAObjectIds_Server = 'nsu=http://opcfoundation.org/UA/;i=2253'; var Arguments: OleVariant; Client: TEasyUAClient; ClientEventHandlers: TClientEventHandlers10; Element1, Element2: _UAContentFilterElement; EndpointDescriptor: string; EventFilter: _UAEventFilter; MonitoredItemArguments: _EasyUAMonitoredItemArguments; MonitoringParameters: _UAMonitoringParameters; Operand1, Operand3: _UASimpleAttributeOperand; Operand2, Operand4: _UALiteralOperand; SourceNodeId: _UANodeId; WhereClause: _UAContentFilterElement; begin EndpointDescriptor := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer'; // Instantiate the client object and hook events Client := TEasyUAClient.Create(nil); ClientEventHandlers := TClientEventHandlers10.Create; Client.OnEventNotification := ClientEventHandlers.Client_EventNotification; WriteLn('Subscribing...'); WhereClause := CoUAContentFilterElement.Create; // Either the severity is >= 500, or the event comes from a specified source node Operand1 := THelperMethods10.UABaseEventObject_Operands_Severity; Operand2 := CoUALiteralOperand.Create; Operand2.Value := 500; Element1 := CoUAContentFilterElement.Create; Element1.FilterOperator := UAFilterOperator_GreaterThanOrEqual; Element1.FilterOperands.Add(Operand1); Element1.FilterOperands.Add(Operand2); Operand3 := THelperMethods10.UABaseEventObject_Operands_SourceNode; SourceNodeId := CoUANodeId.Create; SourceNodeId.ExpandedText := 'nsu=http://opcfoundation.org/Quickstarts/AlarmCondition;ns=2;s=1:Metals/SouthMotor'; Operand4 := CoUALiteralOperand.Create; Operand4.Value := SourceNodeId; Element2 := CoUAContentFilterElement.Create; Element2.FilterOperator := UAFilterOperator_Equals; Element2.FilterOperands.Add(Operand3); Element2.FilterOperands.Add(Operand4); WhereClause.FilterOperator := UAFilterOperator_Or; WhereClause.FilterOperands.Add(Element1); WhereClause.FilterOperands.Add(Element2); EventFilter := CoUAEventFilter.Create; EventFilter.SelectClauses := THelperMethods10.UABaseEventObject_AllFields; EventFilter.WhereClause := WhereClause; MonitoringParameters := CoUAMonitoringParameters.Create; MonitoringParameters.SamplingInterval := 1000; MonitoringParameters.EventFilter := EventFilter; MonitoringParameters.QueueSize := 1000; MonitoredItemArguments := CoEasyUAMonitoredItemArguments.Create; MonitoredItemArguments.EndpointDescriptor.UrlString := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer'; MonitoredItemArguments.NodeDescriptor.NodeId.StandardName := 'Server'; MonitoredItemArguments.MonitoringParameters := MonitoringParameters; //MonitoredItemArguments.SubscriptionParameters.PublishingInterval := 0; MonitoredItemArguments.AttributeId := UAAttributeId_EventNotifier; Arguments := VarArrayCreate([0, 0], varVariant); Arguments[0] := MonitoredItemArguments; Client.SubscribeMultipleMonitoredItems(Arguments); WriteLn('Processing event notifications for 30 seconds...'); PumpSleep(30*1000); WriteLn('Unsubscribing...'); Client.UnsubscribeAllMonitoredItems; WriteLn('Waiting for 5 seconds...'); Sleep(5*1000); WriteLn('Finished.'); VarClear(Arguments); FreeAndNil(Client); FreeAndNil(ClientEventHandlers); end; class function THelperMethods10.ObjectTypeIds_BaseEventType: _UANodeId; var NodeId: _UANodeId; begin NodeId := CoUANodeId.Create; NodeId.StandardName := 'BaseEventType'; Result := NodeId; end; class function THelperMethods10.UAFilterElements_SimpleAttribute(TypeId: _UANodeId; simpleRelativeBrowsePathString: string): _UASimpleAttributeOperand; var BrowsePathParser: _UABrowsePathParser; Operand: _UASimpleAttributeOperand; begin BrowsePathParser := CoUABrowsePathParser.Create; Operand := CoUASimpleAttributeOperand.Create; Operand.TypeId.NodeId := TypeId; Operand.QualifiedNames := BrowsePathParser.ParseRelative(simpleRelativeBrowsePathString).ToUAQualifiedNameCollection; Result := Operand; end; class function THelperMethods10.UABaseEventObject_Operands_EventId: _UASimpleAttributeOperand; begin Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventId'); end; class function THelperMethods10.UABaseEventObject_Operands_EventType: _UASimpleAttributeOperand; begin Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventType'); end; class function THelperMethods10.UABaseEventObject_Operands_NodeId: _UASimpleAttributeOperand; var Operand: _UASimpleAttributeOperand; begin Operand := CoUASimpleAttributeOperand.Create; Operand.TypeId.NodeId.StandardName := 'BaseEventType'; Operand.AttributeId := UAAttributeId_NodeId; Result := Operand; end; class function THelperMethods10.UABaseEventObject_Operands_SourceNode: _UASimpleAttributeOperand; begin Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceNode'); end; class function THelperMethods10.UABaseEventObject_Operands_SourceName: _UASimpleAttributeOperand; begin Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceName'); end; class function THelperMethods10.UABaseEventObject_Operands_Time: _UASimpleAttributeOperand; begin Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Time'); end; class function THelperMethods10.UABaseEventObject_Operands_ReceiveTime: _UASimpleAttributeOperand; begin Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/ReceiveTime'); end; class function THelperMethods10.UABaseEventObject_Operands_LocalTime: _UASimpleAttributeOperand; begin Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/LocalTime'); end; class function THelperMethods10.UABaseEventObject_Operands_Message: _UASimpleAttributeOperand; begin Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Message'); end; class function THelperMethods10.UABaseEventObject_Operands_Severity: _UASimpleAttributeOperand; begin Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Severity'); end; class function THelperMethods10.UABaseEventObject_AllFields: _UAAttributeFieldCollection; var Fields: _UAAttributeFieldCollection; begin Fields := CoUAAttributeFieldCollection.Create; Fields.Add(UABaseEventObject_Operands_NodeId.ToUAAttributeField); Fields.Add(UABaseEventObject_Operands_EventId.ToUAAttributeField); Fields.Add(UABaseEventObject_Operands_EventType.ToUAAttributeField); Fields.Add(UABaseEventObject_Operands_SourceNode.ToUAAttributeField); Fields.Add(UABaseEventObject_Operands_SourceName.ToUAAttributeField); Fields.Add(UABaseEventObject_Operands_Time.ToUAAttributeField); Fields.Add(UABaseEventObject_Operands_ReceiveTime.ToUAAttributeField); Fields.Add(UABaseEventObject_Operands_LocalTime.ToUAAttributeField); Fields.Add(UABaseEventObject_Operands_Message.ToUAAttributeField); Fields.Add(UABaseEventObject_Operands_Severity.ToUAAttributeField); Result := Fields; end;
// This example shows how to specify criteria for event notifications. const UAAttributeId_NodeId = 1; const UAAttributeId_EventNotifier = 12; const UAFilterOperator_Equals = 1; const UAFilterOperator_GreaterThanOrEqual = 5; const UAFilterOperator_Or = 12; const UAObjectIds_Server = 'nsu=http://opcfoundation.org/UA/;i=2253'; class ClientEvents { function EventNotification($Sender, $E) { // Display the event printf("%s\n", $E); } } $EndpointDescriptor = "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer"; // Instantiate the client object and hook events $Client = new COM("OpcLabs.EasyOpc.UA.EasyUAClient"); $ClientEvents = new ClientEvents(); com_event_sink($Client, $ClientEvents, "DEasyUAClientEvents"); $WhereClause = new COM("OpcLabs.EasyOpc.UA.Filtering.UAContentFilterElement"); // Either the severity is >= 500, or the event comes from a specified source node $Operand1 = UABaseEventObject_Operands_Severity(); $Operand2 = new COM("OpcLabs.EasyOpc.UA.Filtering.UALiteralOperand"); $Operand2->Value = 500; $Element1 = new COM("OpcLabs.EasyOpc.UA.Filtering.UAContentFilterElement"); $Element1->FilterOperator = UAFilterOperator_GreaterThanOrEqual; $Element1->FilterOperands->Add($Operand1); $Element1->FilterOperands->Add($Operand2); $Operand3 = UABaseEventObject_Operands_SourceNode(); $SourceNodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $SourceNodeId->ExpandedText = "nsu=http://opcfoundation.org/Quickstarts/AlarmCondition;ns=2;s=1:Metals/SouthMotor"; $Operand4 = new COM("OpcLabs.EasyOpc.UA.Filtering.UALiteralOperand"); $Operand4->Value = $SourceNodeId; $Element2 = new COM("OpcLabs.EasyOpc.UA.Filtering.UAContentFilterElement"); $Element2->FilterOperator = UAFilterOperator_Equals; $Element2->FilterOperands->Add($Operand3); $Element2->FilterOperands->Add($Operand4); $WhereClause->FilterOperator = UAFilterOperator_Or; $WhereClause->FilterOperands->Add($Element1); $WhereClause->FilterOperands->Add($Element2); $EventFilter = new COM("OpcLabs.EasyOpc.UA.UAEventFilter"); $EventFilter->SelectClauses = UABaseEventObject_AllFields(); $EventFilter->WhereClause = $WhereClause; $MonitoringParameters = new COM("OpcLabs.EasyOpc.UA.UAMonitoringParameters"); $MonitoringParameters->SamplingInterval = 1000; $MonitoringParameters->EventFilter = $EventFilter; $MonitoringParameters->QueueSize = 1000; $MonitoredItemArguments = new COM("OpcLabs.EasyOpc.UA.OperationModel.EasyUAMonitoredItemArguments"); $MonitoredItemArguments->EndpointDescriptor->UrlString = $EndpointDescriptor; $MonitoredItemArguments->NodeDescriptor->NodeId->StandardName = "Server"; $MonitoredItemArguments->MonitoringParameters = $MonitoringParameters; /$MonitoredItemArguments->SubscriptionParameters->PublishingInterval = 0; $MonitoredItemArguments->AttributeId = UAAttributeId_EventNotifier; $arguments[0] = $MonitoredItemArguments; printf("Subscribing...\n"); $Client->SubscribeMultipleMonitoredItems($arguments); printf("Processing monitored item changed events for 30 seconds...\n"); $startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 30); printf("Unsubscribing...\n"); $Client->UnsubscribeAllMonitoredItems; printf("Waiting for 5 seconds...\n"); $startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 5); function ObjectTypeIds_BaseEventType() { $NodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId->StandardName = "BaseEventType"; return $NodeId; } function UAFilterElements_SimpleAttribute($TypeId, $simpleRelativeBrowsePathString) { $BrowsePathParser = new COM("OpcLabs.EasyOpc.UA.Navigation.Parsing.UABrowsePathParser"); $Operand = new COM("OpcLabs.EasyOpc.UA.Filtering.UASimpleAttributeOperand"); $Operand->TypeId->NodeId = $TypeId; $Operand->QualifiedNames = $BrowsePathParser->ParseRelative($simpleRelativeBrowsePathString)->ToUAQualifiedNameCollection; return $Operand; } function UABaseEventObject_Operands_NodeId() { $Operand = new COM("OpcLabs.EasyOpc.UA.Filtering.UASimpleAttributeOperand"); $Operand->TypeId->NodeId->StandardName = "BaseEventType"; $Operand->AttributeId = UAAttributeId_NodeId; return $Operand; } function UABaseEventObject_Operands_EventId() { return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/EventId"); } function UABaseEventObject_Operands_EventType() { return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/EventType"); } function UABaseEventObject_Operands_SourceNode() { return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/SourceNode"); } function UABaseEventObject_Operands_SourceName() { return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/SourceName"); } function UABaseEventObject_Operands_Time() { return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Time"); } function UABaseEventObject_Operands_ReceiveTime() { return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/ReceiveTime"); } function UABaseEventObject_Operands_LocalTime() { return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/LocalTime"); } function UABaseEventObject_Operands_Message() { return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Message"); } function UABaseEventObject_Operands_Severity() { return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Severity"); } function UABaseEventObject_AllFields() { $Fields = new COM("OpcLabs.EasyOpc.UA.UAAttributeFieldCollection"); $Fields->Add(UABaseEventObject_Operands_NodeId()->ToUAAttributeField); $Fields->Add(UABaseEventObject_Operands_EventId()->ToUAAttributeField); $Fields->Add(UABaseEventObject_Operands_EventType()->ToUAAttributeField); $Fields->Add(UABaseEventObject_Operands_SourceNode()->ToUAAttributeField); $Fields->Add(UABaseEventObject_Operands_SourceName()->ToUAAttributeField); $Fields->Add(UABaseEventObject_Operands_Time()->ToUAAttributeField); $Fields->Add(UABaseEventObject_Operands_ReceiveTime()->ToUAAttributeField); $Fields->Add(UABaseEventObject_Operands_LocalTime()->ToUAAttributeField); $Fields->Add(UABaseEventObject_Operands_Message()->ToUAAttributeField); $Fields->Add(UABaseEventObject_Operands_Severity()->ToUAAttributeField); return $Fields; }
// This example shows how to specify criteria for event notifications. type TClientEventHandlers3 = class procedure OnEventNotification( Sender: TObject; sender0: OleVariant; eventArgs: _EasyUAEventNotificationEventArgs); end; procedure TClientEventHandlers3.OnEventNotification( Sender: TObject; sender0: OleVariant; eventArgs: _EasyUAEventNotificationEventArgs); begin // Display the event WriteLn(eventArgs.ToString); end; class procedure WhereClause.Main; function ToUAAttributeField(Operand: UASimpleAttributeOperand): UAAttributeField; var AttributeField: UAAttributeField; begin AttributeField := CoUAAttributeField.Create; AttributeField.Operand := Operand; ToUAAttributeField := AttributeField; end; function ObjectTypeIds_BaseEventType: UANodeId; var NodeId: UANodeId; begin NodeId := CoUANodeId.Create; NodeId.StandardName := 'BaseEventType'; ObjectTypeIds_BaseEventType := NodeId; end; function UAFilterElements_SimpleAttribute(TypeId: UANodeId; SimpleRelativeBrowsePathString: string): UASimpleAttributeOperand; var Operand: UASimpleAttributeOperand; BrowsePathParser: UABrowsePathParser; begin BrowsePathParser := CoUABrowsePathParser.Create; Operand := CoUASimpleAttributeOperand.Create; Operand.TypeId.NodeId := TypeId; Operand.QualifiedNames := BrowsePathParser.ParseRelative(SimpleRelativeBrowsePathString).ToUAQualifiedNameCollection; UAFilterElements_SimpleAttribute := Operand; end; function UABaseEventObject_Operands_NodeId: UASimpleAttributeOperand; var Operand: UASimpleAttributeOperand; begin Operand := CoUASimpleAttributeOperand.Create; Operand.TypeId.NodeId.StandardName := 'BaseEventType'; Operand.AttributeId := UAAttributeId_NodeId; UABaseEventObject_Operands_NodeId := Operand; end; function UABaseEventObject_Operands_EventId: UASimpleAttributeOperand; begin UABaseEventObject_Operands_EventId := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventId'); end; function UABaseEventObject_Operands_EventType: UASimpleAttributeOperand; begin UABaseEventObject_Operands_EventType := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventType'); end; function UABaseEventObject_Operands_SourceNode: UASimpleAttributeOperand; begin UABaseEventObject_Operands_SourceNode := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceNode'); end; function UABaseEventObject_Operands_SourceName: UASimpleAttributeOperand; begin UABaseEventObject_Operands_SourceName := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceName'); end; function UABaseEventObject_Operands_Time: UASimpleAttributeOperand; begin UABaseEventObject_Operands_Time := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Time'); end; function UABaseEventObject_Operands_ReceiveTime: UASimpleAttributeOperand; begin UABaseEventObject_Operands_ReceiveTime := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/ReceiveTime'); end; function UABaseEventObject_Operands_LocalTime: UASimpleAttributeOperand; begin UABaseEventObject_Operands_LocalTime := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/LocalTime'); end; function UABaseEventObject_Operands_Message: UASimpleAttributeOperand; begin UABaseEventObject_Operands_Message := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Message'); end; function UABaseEventObject_Operands_Severity: UASimpleAttributeOperand; begin UABaseEventObject_Operands_Severity := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Severity'); end; function UABaseEventObject_AllFields: UAAttributeFieldCollection; var Fields: UAAttributeFieldCollection; begin Fields := CoUAAttributeFieldCollection.Create; Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_NodeId)); Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_EventId)); Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_EventType)); Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_SourceNode)); Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_SourceName)); Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_Time)); Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_ReceiveTime)); Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_LocalTime)); Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_Message)); Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_Severity)); UABaseEventObject_AllFields := Fields; end; var Arguments: OleVariant; EvsClient: TEvsEasyUAClient; Client: EasyUAClient; ClientEventHandlers: TClientEventHandlers3; Handle: Cardinal; HandleArray: OleVariant; MonitoredItemArguments: EasyUAMonitoredItemArguments; MonitoringParameters: UAMonitoringParameters; EventFilter: UAEventFilter; WhereClause: UAContentFilterElement; Operand1: UASimpleAttributeOperand; Operand2: UALiteralOperand; Operand3: UASimpleAttributeOperand; Operand4: UALiteralOperand; SourceNodeId: UANodeId; Element1, Element2: UAContentFilterElement; BaseEventType: UANodeId; begin // Instantiate the client object and hook events EvsClient := TEvsEasyUAClient.Create(nil); Client := EvsClient.ComServer; ClientEventHandlers := TClientEventHandlers3.Create; EvsClient.OnEventNotification := @ClientEventHandlers.OnEventNotification; WriteLn('Subscribing...'); WhereClause := CoUAContentFilterElement.Create; BaseEventType := CoUaNodeId.Create; BaseEventType.StandardName := 'BaseEventType'; // Either the severity is >= 500, or the event comes from a specified source node Operand1 := UABaseEventObject_Operands_Severity; Operand2 := CoUALiteralOperand.Create; Operand2.Value := 500; Element1 := CoUAContentFilterElement.Create; Element1.FilterOperator := UAFilterOperator_GreaterThanOrEqual; Element1.FilterOperands.Add(Operand1); Element1.FilterOperands.Add(Operand2); Operand3 := UABaseEventObject_Operands_SourceNode; SourceNodeId := CoUANodeId.Create; SourceNodeId.ExpandedText := 'nsu=http://opcfoundation.org/Quickstarts/AlarmCondition;ns=2;s=1:Metals/SouthMotor'; Operand4 := CoUALiteralOperand.Create; Operand4.Value := SourceNodeId; Element2 := CoUAContentFilterElement.Create; Element2.FilterOperator := UAFilterOperator_Equals; Element2.FilterOperands.Add(Operand3); Element2.FilterOperands.Add(Operand4); WhereClause.FilterOperator := UAFilterOperator_Or; WhereClause.FilterOperands.Add(Element1); WhereClause.FilterOperands.Add(Element2); EventFilter := CoUAEventFilter.Create; EventFilter.SelectClauses := UABaseEventObject_AllFields; EventFilter.WhereClause := WhereClause; MonitoringParameters := CoUAMonitoringParameters.Create; MonitoringParameters.SamplingInterval := 1000; MonitoringParameters.EventFilter := EventFilter; MonitoringParameters.QueueSize := 1000; MonitoredItemArguments := CoEasyUAMonitoredItemArguments.Create; MonitoredItemArguments.EndpointDescriptor.UrlString := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer'; MonitoredItemArguments.NodeDescriptor.NodeId.StandardName := 'Server'; MonitoredItemArguments.MonitoringParameters := MonitoringParameters; //MonitoredItemArguments.SubscriptionParameters.PublishingInterval := 0; MonitoredItemArguments.AttributeId := UAAttributeId_EventNotifier; Arguments := VarArrayCreate([0, 0], varVariant); Arguments[0] := MonitoredItemArguments; TVarData(HandleArray).VType := varArray or varVariant; TVarData(HandleArray).VArray := PVarArray( Client.SubscribeMultipleMonitoredItems(PSafeArray(TVarData(Arguments).VArray))); WriteLn('Processing event notifications for 30 seconds...'); PumpSleep(30*1000); WriteLn('Unsubscribing...'); Client.UnsubscribeAllMonitoredItems; WriteLn('Waiting for 5 seconds...'); PumpSleep(5*1000); WriteLn('Finished...'); end;
Copyright © 2004-2023 CODE Consulting and Development, s.r.o., Plzen. All rights reserved. Web page: www.opclabs.com
Send Documentation Feedback. Resources: Knowledge Base. Technical support: Online Forums, FAQ.